from flask import Flask, jsonify, request
from flask_sqlalchemy import SQLAlchemy
from flask_jwt_extended import JWTManager, create_access_token, jwt_required, get_jwt_identity
import datetime
import requests  # 新增：用于调用微信接口
import base64    # 新增：用于解密时的Base64解码
import json    #解析加密的JSON 数据
from Crypto.Cipher import AES  # 新增：AES解密（来自pycryptodome）

from dotenv import load_dotenv 
import os  
from sqlalchemy.exc import IntegrityError

load_dotenv()  # 加载.env文件中的环境变量

WECHAT_APP_ID = os.getenv('WECHAT_APP_ID')       # 你在.env中配置的小程序APPID
WECHAT_APP_SECRET = os.getenv('WECHAT_APP_SECRET') # 你在.env中配置的小程序密钥
WECHAT_CODE2SESSION_URL = 'https://api.weixin.qq.com/sns/jscode2session'  # 微信code换session接口

app = Flask(__name__)
# 配置数据库连接
# 生产环境数据库配置

app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# JWT配置 - 生产环境使用更安全的密钥

app.config['SQLALCHEMY_DATABASE_URI'] = f"mysql+pymysql://{os.getenv('DB_USER')}:{os.getenv('DB_PASSWORD')}@{os.getenv('DB_HOST')}:{os.getenv('DB_PORT')}/{os.getenv('DB_NAME')}"
app.config['JWT_SECRET_KEY'] = os.getenv('JWT_SECRET_KEY')
app.config['JWT_ACCESS_TOKEN_EXPIRES'] = datetime.timedelta(days=int(os.getenv('JWT_ACCESS_TOKEN_EXPIRES')))

db = SQLAlchemy(app)
jwt = JWTManager(app)

# 在 jwt = JWTManager(app) 之后添加
@jwt.expired_token_loader
def expired_token_callback(jwt_header, jwt_payload):
    return jsonify({
        'code': 401,
        'msg': 'Token已过期，请重新登录'
    }), 401

@jwt.invalid_token_loader
def invalid_token_callback(error):
    return jsonify({
        'code': 401,
        'msg': 'Token无效，请重新登录'
    }), 401

@jwt.unauthorized_loader
def missing_token_callback(error):
    return jsonify({
        'code': 401,
        'msg': '缺少Token，请先登录'
    }), 401

app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {
    'pool_size': 10,           # 连接池大小
    'max_overflow': 20,        # 临时连接数
    'pool_recycle': 3600,      # 1小时后自动回收连接（防超时）
    'pool_pre_ping': True      # 连接前检查有效性
}

def wechat_code_to_openid(code):
    """
    用前端传递的code，调用微信接口换取openid和session_key
    :param code: 前端wx.login()获取的code
    :return: dict -> {'openid': '用户唯一标识', 'session_key': '解密用的密钥'}
    """
    params = {
        'appid': WECHAT_APP_ID,
        'secret': WECHAT_APP_SECRET,
        'js_code': code,
        'grant_type': 'authorization_code'
    }
    try:
        response = requests.get(WECHAT_CODE2SESSION_URL, params=params, timeout=10)
        response.raise_for_status()  # 新增：触发HTTP错误（如404/500）
        result = response.json()
        # 处理微信接口错误（如code过期、appid错误）
        if 'errcode' in result and result['errcode'] != 0:
            raise Exception(f"微信接口错误[{result['errcode']}]: {result.get('errmsg', '未知错误')}")
        # 检查是否返回openid
        if not result.get('openid'):
            raise Exception("未获取到openid")
        return {
            'openid': result['openid'],
            'session_key': result.get('session_key')  # session_key用于解密encryptedData
        }
    except requests.exceptions.HTTPError as e:
        raise Exception(f"微信接口HTTP错误: {str(e)}")  # 新增：捕获HTTP错误
    except requests.exceptions.RequestException as e:
        raise Exception(f"请求微信服务器失败: {str(e)}")  # 捕获超时/连接错误
    except Exception as e:
        raise Exception(f"code换openid失败: {str(e)}")

def decrypt_wechat_encrypted_data(encrypted_data, iv, session_key):
    try:
        # 1. Base64解码
        session_key = base64.b64decode(session_key)
        encrypted_data = base64.b64decode(encrypted_data)
        iv = base64.b64decode(iv)
        
        # 2. AES解密
        cipher = AES.new(session_key, AES.MODE_CBC, iv)
        decrypted_bytes = cipher.decrypt(encrypted_data)
        
        # 3. 修复：先判断解密后的数据是否为空
        if not decrypted_bytes:
            raise Exception("解密后数据为空")
        # 去除PKCS#7填充
        unpad = lambda s: s[:-ord(s[len(s)-1:])]
        decrypted_str = unpad(decrypted_bytes).decode('utf-8')
        
        # 4. 解析JSON并验证appid
        decrypted_data = json.loads(decrypted_str)
        if decrypted_data['watermark']['appid'] != WECHAT_APP_ID:
            raise Exception("解密数据非法：appid不匹配")
        
        return decrypted_data
    except Exception as e:
        raise Exception(f"解密encryptedData失败: {str(e)}")

# 数据模型定义 - 映射数据库表
class User(db.Model):
    __tablename__ = 'user'
    id = db.Column(db.Integer, primary_key=True)
    openid = db.Column(db.String(64), unique=True, nullable=False)  # 微信唯一标识，必选
    wechat_name = db.Column(db.String(32), nullable=True)  # 改为允许为空（用户可能拒绝授权昵称）
    wechat_avatar = db.Column(db.String(255), nullable=True)  # 允许为空（用户可能拒绝授权头像）
    phone = db.Column(db.String(11), unique=True, nullable=True)  # 改为允许为空（登录时无需手机号）
    real_name = db.Column(db.String(32), nullable=True)  # 新增：存储真实姓名（医生/患者通用）
    role = db.Column(db.Integer, nullable=False, default=0)  # 新增默认值0（未指定角色）
    status = db.Column(db.Integer, default=1)
    create_time = db.Column(db.DateTime, default=datetime.datetime.now())  # 新增默认值（创建时自动填充）
    update_time = db.Column(db.DateTime, default=datetime.datetime.now(), onupdate=datetime.datetime.now())  # 新增自动更新

class UserDoctor(db.Model):
    __tablename__ = 'user_doctor'
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, nullable=False)
    hospital = db.Column(db.String(64), nullable=False)
    department = db.Column(db.String(32), nullable=False)
    position = db.Column(db.String(32), nullable=False)
    create_time = db.Column(db.DateTime, default=datetime.datetime.now())
    update_time = db.Column(db.DateTime, default=datetime.datetime.now(), onupdate=datetime.datetime.now())

class UserPatient(db.Model):
    __tablename__ = 'user_patient'
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, nullable=False)
    gender = db.Column(db.Integer, nullable=False)
    age = db.Column(db.Integer, nullable=False)
    id_card = db.Column(db.String(18), unique=True, nullable=False)
    create_time = db.Column(db.DateTime, default=datetime.datetime.now())
    update_time = db.Column(db.DateTime, default=datetime.datetime.now(), onupdate=datetime.datetime.now())

# 新增：医生-患者绑定关系表（存储医生绑定的患者）
class DoctorPatientBind(db.Model):
    __tablename__ = 'doctor_patient_bind'  
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)  
    doctor_id = db.Column(db.Integer, nullable=False)  
    patient_id = db.Column(db.Integer, nullable=False)  
  
    bind_time = db.Column(db.DateTime, default=datetime.datetime.now, nullable=False)
   
    status = db.Column(db.Integer, default=1, nullable=False)

    # 1. 联合唯一约束：与数据库的_unique_doctor_patient_unique约束名完全一致
    # 2. 外键约束：与数据库的外键配置一致（确保关联user表id，级联删除）
    __table_args__ = (
        db.UniqueConstraint('doctor_id', 'patient_id', name='_doctor_patient_unique'),
        db.ForeignKeyConstraint(['doctor_id'], ['user.id'], ondelete='CASCADE'),
        db.ForeignKeyConstraint(['patient_id'], ['user.id'], ondelete='CASCADE'),
    )

class ScaleAssessment(db.Model):
    __tablename__ = 'scale_assessment'
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, nullable=False)
    assessor_id = db.Column(db.Integer, nullable=False)
    assessment_date = db.Column(db.Date, nullable=False)
    hamd_total = db.Column(db.Integer, nullable=False)
    hama_total = db.Column(db.Integer, nullable=False)
    ymrs_total = db.Column(db.Integer, nullable=False)
    assessment_notes = db.Column(db.Text)
    create_time = db.Column(db.DateTime, default=datetime.datetime.now())
    update_time = db.Column(db.DateTime, default=datetime.datetime.now(), onupdate=datetime.datetime.now())

class ScaleHama(db.Model):
    """HAMA焦虑量表模型（对应 scale_hama 表）"""
    __tablename__ = 'scale_hama'
    
    id = db.Column(db.Integer, primary_key=True)
    assessment_id = db.Column(db.Integer, nullable=False)  # 关联评估记录ID
    item1_irritability = db.Column(db.Integer, nullable=False)  # 易激惹
    item2_tension = db.Column(db.Integer, nullable=False)  # 紧张
    item3_fears = db.Column(db.Integer, nullable=False)  # 害怕
    item4_insomnia = db.Column(db.Integer, nullable=False)  # 失眠
    item5_cognition = db.Column(db.Integer, nullable=False)  # 认知功能
    item6_depressed_mood = db.Column(db.Integer, nullable=False)  # 抑郁心境
    item7_somatic_muscle = db.Column(db.Integer, nullable=False)  # 躯体性肌肉症状
    item8_somatic_sensory = db.Column(db.Integer, nullable=False)  # 躯体性感觉症状
    item9_cardiovascular = db.Column(db.Integer, nullable=False)  # 心血管系统症状
    item10_respiratory = db.Column(db.Integer, nullable=False)  # 呼吸系统症状
    item11_gastrointestinal = db.Column(db.Integer, nullable=False)  # 胃肠道症状
    item12_genitourinary = db.Column(db.Integer, nullable=False)  # 泌尿生殖系统症状
    item13_autonomic = db.Column(db.Integer, nullable=False)  # 自主神经症状
    item14_behavior = db.Column(db.Integer, nullable=False)  # 行为表现


class ScaleHamd17(db.Model):
    """HAMD17抑郁量表模型（对应 scale_hamd17 表）"""
    __tablename__ = 'scale_hamd17'
    
    id = db.Column(db.Integer, primary_key=True)
    assessment_id = db.Column(db.Integer, nullable=False)  # 关联评估记录ID
    item1_depression = db.Column(db.Integer, nullable=False)  # 抑郁情绪
    item2_guilt = db.Column(db.Integer, nullable=False)  # 罪恶感
    item3_suicide = db.Column(db.Integer, nullable=False)  # 自杀
    item4_sleep_initial = db.Column(db.Integer, nullable=False)  # 入睡困难
    item5_sleep_middle = db.Column(db.Integer, nullable=False)  # 睡眠不深
    item6_sleep_late = db.Column(db.Integer, nullable=False)  # 早醒
    item7_activity = db.Column(db.Integer, nullable=False)  # 工作和兴趣
    item8_retardation = db.Column(db.Integer, nullable=False)  # 迟滞
    item9_agitation = db.Column(db.Integer, nullable=False)  # 激越
    item10_anxiety_psychic = db.Column(db.Integer, nullable=False)  # 精神性焦虑
    item11_anxiety_somatic = db.Column(db.Integer, nullable=False)  # 躯体性焦虑
    item12_somatic_symptoms = db.Column(db.Integer, nullable=False)  # 胃肠道症状
    item13_general_somatic = db.Column(db.Integer, nullable=False)  # 全身症状
    item14_genital = db.Column(db.Integer, nullable=False)  # 性症状
    item15_hypochondriasis = db.Column(db.Integer, nullable=False)  # 疑病
    item16_weight = db.Column(db.Integer, nullable=False)  # 体重减轻
    item17_insight = db.Column(db.Integer, nullable=False)  # 自知力


class ScaleYmrs(db.Model):
    """YMRS躁狂量表模型（对应 scale_ymrs 表）"""
    __tablename__ = 'scale_ymrs'
    
    id = db.Column(db.Integer, primary_key=True)
    assessment_id = db.Column(db.Integer, nullable=False)  # 关联评估记录ID
    item1_mood_elevated = db.Column(db.Integer, nullable=False)  # 情绪高涨
    item2_activity = db.Column(db.Integer, nullable=False)  # 活动增多
    item3_sleep = db.Column(db.Integer, nullable=False)  # 睡眠减少
    item4_irritability = db.Column(db.Integer, nullable=False)  # 易激惹
    item5_speech_rate = db.Column(db.Integer, nullable=False)  # 言语速度和量
    item6_speech_pressured = db.Column(db.Integer, nullable=False)  # 言语迫促
    item7_thought_content = db.Column(db.Integer, nullable=False)  # 思维内容
    item8_grandiosity = db.Column(db.Integer, nullable=False)  # 夸大
    item9_distractibility = db.Column(db.Integer, nullable=False)  # 随境转移
    item10_hostility = db.Column(db.Integer, nullable=False)  # 敌意
    item11_grandiosity_severity = db.Column(db.Integer, nullable=False)  # 夸大严重程度


# 认证接口
# 认证接口（改造后：支持接收wx.getUserProfile的用户信息）
@app.route('/api/v1/auth/login', methods=['POST'])
def login():
    try:
        # 1. 接收前端传递的参数（包含code、用户信息、加密数据）
        data = request.get_json()
        code = data.get('code')  # 前端wx.login()获取的code（必选）
        user_info = data.get('user_info', {})  # 前端wx.getUserProfile()获取的明文信息（如昵称、头像）
        encrypted_data = data.get('encrypted_data')  # 前端传递的加密信息（可选，用于获取unionId）
        iv = data.get('iv')  # 前端传递的解密向量（可选，与encrypted_data配套）

        # 2. 校验必填参数
        if not code:
            return jsonify({'code': 400, 'msg': '缺少code参数'})

        # 3. 调用微信接口，用code换取openid和session_key
        wechat_result = wechat_code_to_openid(code)
        openid = wechat_result['openid']
        session_key = wechat_result.get('session_key')

        # 4. （可选）解密encrypted_data，获取unionId（多小程序/公众号统一用户标识）
        union_id = None
        if encrypted_data and iv and session_key:
            decrypted_data = decrypt_wechat_encrypted_data(encrypted_data, iv, session_key)
            union_id = decrypted_data.get('unionId')  # 提取unionId（如需存储，需在User模型新增union_id字段）

        # 5. 查询/创建用户，并更新微信信息
        user = User.query.filter_by(openid=openid).first()
        if not user:
            # 5.1 新建用户：用wx.getUserProfile的信息填充
            user = User(
                openid=openid,
                wechat_name=user_info.get('nickName', ''),  # 微信昵称（明文）
                wechat_avatar=user_info.get('avatarUrl', ''),  # 微信头像URL（明文）
                # phone留空（后续用户完善）、role默认0（未指定角色）
                # create_time/update_time由模型默认值自动填充
            )
            db.session.add(user)
        else:
            # 5.2 已有用户：更新微信信息（用户可能修改了微信昵称/头像）
            if user_info.get('nickName'):
                user.wechat_name = user_info.get('nickName')
            if user_info.get('avatarUrl'):
                user.wechat_avatar = user_info.get('avatarUrl')
            # update_time由模型onupdate自动更新

        # 6. 提交数据库
        db.session.commit()

        # 7. 生成JWT Token，返回结果给前端
        access_token = create_access_token(identity=user.id)
        return jsonify({
            'code': 200,
            'msg': '登录成功',
            'data': {
                'token': access_token,
                'user_id': user.id,
                'role': user.role,
                'user_info': {  # 返回用户信息，前端可直接显示（避免二次请求）
                    'wechat_name': user.wechat_name,  # nickname
                    'wechat_avatar': user.wechat_avatar,  # avatar
                    'real_name': user.real_name  # 新增：真实姓名（可能为空，需用户后续完善）
                }
            }
        })

    # 8. 异常处理（分类返回错误信息，便于调试）
    except requests.exceptions.RequestException as e:
        return jsonify({'code': 500, 'msg': f'请求微信服务器失败: {str(e)}'})
    except Exception as e:
        db.session.rollback()  # 数据库回滚，防止脏数据
        return jsonify({'code': 500, 'msg': f'登录失败: {str(e)}'})

# 获取当前用户信息
@app.route('/api/v1/auth/user-info', methods=['GET'])
@jwt_required()
def get_user_info():
    user_id = get_jwt_identity()
    user = User.query.get(user_id)
    if not user:
        return jsonify({'code': 404, 'msg': '用户不存在'})
    
    return jsonify({
        'code': 200,
        'data': {
            'id': user.id,
            'wechat_name': user.wechat_name,  # nickname（微信昵称）
            'wechat_avatar': user.wechat_avatar,  # avatar（微信头像）
            'real_name': user.real_name,  # 新增：真实姓名
            'phone': user.phone,
            'role': user.role,
            'status': user.status,
            'create_time': user.create_time.strftime('%Y-%m-%d %H:%M:%S')
        }
    })

# 完善用户信息接口（如绑定手机号、选择角色）
@app.route('/api/v1/auth/complete-info', methods=['POST'])
@jwt_required()
def complete_user_info():
    try:
        user_id = get_jwt_identity()
        user = User.query.get(user_id)
        if not user:
            return jsonify({'code': 404, 'msg': '用户不存在'})
        
        data = request.get_json()
        phone = data.get('phone')  # 用户填写的手机号
        role = data.get('role')    # 用户选择的角色（1=医生，2=患者）

        # 校验参数
        if not phone or not role in [1, 2]:
            return jsonify({'code': 400, 'msg': '缺少手机号或角色选择错误'})
        
        # 检查手机号是否已被占用
        if User.query.filter_by(phone=phone).first() and User.query.filter_by(phone=phone).first().id != user_id:
            return jsonify({'code': 400, 'msg': '手机号已被绑定'})
        
        # 更新用户信息
        user.phone = phone
        user.role = role
        # update_time由模型onupdate自动更新
        db.session.commit()

        return jsonify({'code': 200, 'msg': '信息完善成功', 'data': {'role': user.role}})
    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 500, 'msg': f'完善信息失败: {str(e)}'})

# 医生信息接口
@app.route('/api/v1/users/doctor', methods=['POST'])
@jwt_required()
def create_doctor_info():
    user_id = get_jwt_identity()
    data = request.get_json()
    
    # 验证用户是否存在
    user = User.query.get(user_id)
    if not user:
        return jsonify({'code': 404, 'msg': '用户不存在'})

     # 新增：校验用户角色是否为医生，避免重复创建
    if user.role != 1:
        return jsonify({'code': 403, 'msg': '仅医生角色可完善医生信息'})
    
    # 更新用户基础信息（补充真实姓名存储）
    user.phone = data['phone']
    user.real_name = data['real_name']  # 存储真实姓名到User表
    # 保留微信昵称
    # user.wechat_name = data['real_name']  # 注释掉这行
    
    # 创建医生信息
    doctor = UserDoctor(
        user_id=user_id,
        hospital=data.get('hospital'),
        department=data.get('department'),
        position=data.get('position'),
    )
    db.session.add(doctor)
    
    db.session.commit()
    
    return jsonify({
        'code': 200,
        'msg': '医生信息创建成功',
        'data': {'id': doctor.id}
    })

# 1. 用户管理模块 - 医生信息接口（续）
# ------------------------------
# 1.1 获取当前登录医生的详情（医生查看自己的信息）
@app.route('/api/v1/users/doctor/self', methods=['GET'])
@jwt_required()
def get_self_doctor_info():
    user_id = get_jwt_identity()
    # 1. 验证用户是否为医生角色
    user = User.query.get(user_id)
    if not user:
        return jsonify({'code': 404, 'msg': '用户不存在'})
    if user.role != 1:  # 1=医生角色
        return jsonify({'code': 403, 'msg': '权限不足，非医生用户'})
    
    # 2. 查询医生详情
    doctor_info = UserDoctor.query.filter_by(user_id=user_id).first()
    if not doctor_info:
        return jsonify({'code': 404, 'msg': '医生信息未完善'})
    
    # 3. 构造返回数据
    return jsonify({
        'code': 200,
        'data': {
            'user_id': doctor_info.user_id,
            'hospital': doctor_info.hospital,
            'department': doctor_info.department,
            'position': doctor_info.position,
            'create_time': doctor_info.create_time.strftime('%Y-%m-%d %H:%M:%S'),
            'update_time': doctor_info.update_time.strftime('%Y-%m-%d %H:%M:%S')
        }
    })

# 1.2 更新医生信息（医生修改自己的信息）
from datetime import datetime  # 导入datetime类

@app.route('/api/v1/users/doctor/self', methods=['PUT'])
@jwt_required()
def update_self_doctor_info():
    user_id = get_jwt_identity()
    data = request.get_json()

    # 1. 验证用户身份
    user = User.query.get(user_id)
    if not user or user.role != 1:
        return jsonify({'code': 403, 'msg': '权限不足，非医生用户'})

    # 2. 查询医生信息
    doctor_info = UserDoctor.query.filter_by(user_id=user_id).first()
    if not doctor_info:
        return jsonify({'code': 404, 'msg': '医生信息未完善，无法更新'})

    # 3. 更新字段（只更新传入的非空字段）
    if 'hospital' in data and data['hospital']:
        doctor_info.hospital = data['hospital']
    if 'department' in data and data['department']:
        doctor_info.department = data['department']
    if 'position' in data and data['position']:
        doctor_info.position = data['position']
    doctor_info.update_time = datetime.now()  # 调用datetime类的now方法

    # 4. 提交事务
    try:
        db.session.commit()
        return jsonify({'code': 200, 'msg': '医生信息更新成功'})
    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 500, 'msg': f'更新失败：{str(e)}'})

# 1.3 管理员查询指定医生信息（需管理员权限）
@app.route('/api/v1/admin/doctors/<int:doctor_user_id>', methods=['GET'])
@jwt_required()
def admin_get_doctor(doctor_user_id):
    admin_id = get_jwt_identity()
    # 1. 验证管理员身份
    admin = User.query.get(admin_id)
    if not admin or admin.role != 3:  # 3=管理员角色
        return jsonify({'code': 403, 'msg': '权限不足，非管理员'})
    
    # 2. 查询医生信息
    doctor_info = UserDoctor.query.filter_by(user_id=doctor_user_id).first()
    doctor_base = User.query.get(doctor_user_id)
    if not doctor_base or not doctor_info:
        return jsonify({'code': 404, 'msg': '医生不存在'})
    
    return jsonify({
        'code': 200,
        'data': {
            'user_id': doctor_user_id,
            'wechat_name': doctor_base.wechat_name,  # 微信昵称
            'wechat_avatar': doctor_base.wechat_avatar,  # 头像
            'real_name': doctor_base.real_name,  # 新增：真实姓名
            'phone': doctor_base.phone,
            'hospital': doctor_info.hospital,
            'department': doctor_info.department,
            'position': doctor_info.position,
            'status': doctor_base.status  # 账号状态（1=正常，0=禁用）
        }
    })


# ------------------------------


@app.route('/api/v1/users/patient', methods=['POST'])
@jwt_required()
def create_patient_info():
    doctor_id = get_jwt_identity()
    data = request.get_json()
    
    # 1. 验证医生身份
    doctor = User.query.get(doctor_id)
    if not doctor or doctor.role != 1:
        return jsonify({'code': 403, 'msg': '权限不足，非医生用户'})
    
    # 2. 验证必填参数
    required_fields = ['user_id', 'gender', 'age', 'id_card']
    for field in required_fields:
        if field not in data or not data[field]:
            return jsonify({'code': 400, 'msg': f'缺少必填参数：{field}'})
    
    # 3. 验证患者基础信息存在（修复：先判断是否为None）
    patient_base = User.query.get(data['user_id'])
    if not patient_base:
        return jsonify({'code': 404, 'msg': '患者基础信息不存在'})
    # 只有患者存在时，才判断角色
    if patient_base.role != 2:
        patient_base.role = 2
        # 修复：用模型默认的update_time自动更新，无需手动传值
        # patient_base.update_time = datetime.datetime.now()
    
    # 4. 更新用户基础信息（补充真实姓名存储）
    patient_base.phone = data['phone']
    patient_base.real_name = data['real_name']  # 存储真实姓名到User表
    # 保留微信昵称（不覆盖），前端可根据需要选择显示哪个
    # patient_base.wechat_name = data['real_name']  # 注释掉这行，避免覆盖微信昵称
    
    # 5. 创建患者详情（修复：无需手动传时间）
    try:
        patient_info = UserPatient(
            user_id=data['user_id'],
            gender=data['gender'],
            age=data['age'],
            id_card=data['id_card']
        )
        db.session.add(patient_info)
        db.session.commit()
        return jsonify({
            'code': 200,
            'msg': '患者信息创建成功',
            'data': {'patient_id': patient_info.id}
        })
    except IntegrityError:
        db.session.rollback()
        return jsonify({'code': 400, 'msg': '身份证号已存在'})
    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 500, 'msg': f'创建失败：{str(e)}'})

# ------------------------------
# 3. 量表评估模块 - 评估记录接口
# ------------------------------
# 3.1 医生创建患者评估记录（主记录）- 新增绑定校验
@app.route('/api/v1/assessments', methods=['POST'])
@jwt_required()
def create_assessment():
    doctor_id = get_jwt_identity()
    data = request.get_json()
    
    # 1. 验证医生身份（原逻辑保留）
    if not User.query.get(doctor_id) or User.query.get(doctor_id).role != 1:
        return jsonify({'code': 403, 'msg': '权限不足，非医生用户'})
    
    # 2. 验证必填参数（原逻辑保留）
    required_fields = ['user_id', 'assessment_date', 'hamd_total', 'hama_total', 'ymrs_total']
    for field in required_fields:
        if field not in data or not data[field]:
            return jsonify({'code': 400, 'msg': f'缺少必填参数：{field}'})
    
    # -------------------------- 新增：绑定校验 --------------------------
    patient_id = data['user_id']
    # 检查医生是否已绑定该患者（仅允许为已绑定患者创建评估）
    is_bound = DoctorPatientBind.query.filter(
        DoctorPatientBind.doctor_id == doctor_id,
        DoctorPatientBind.patient_id == patient_id,
        DoctorPatientBind.status == 1
    ).first()
    if not is_bound:
        return jsonify({'code': 403, 'msg': '未绑定该患者，请先绑定再创建评估记录'})
    # -------------------------------------------------------------------
    
    # 3. 验证患者存在（原逻辑保留）
    if not User.query.get(data['user_id']) or User.query.get(data['user_id']).role != 2:
        return jsonify({'code': 404, 'msg': '患者不存在'})
    
    # 4. 创建评估记录（原逻辑保留）
    try:
        # 转换日期格式（前端传 'YYYY-MM-DD'，后端转 datetime.date）
        assessment_date = datetime.datetime.strptime(data['assessment_date'], '%Y-%m-%d').date()
        
        assessment = ScaleAssessment(
            user_id=data['user_id'],
            assessor_id=doctor_id,
            assessment_date=assessment_date,
            hamd_total=data['hamd_total'],
            hama_total=data['hama_total'],
            ymrs_total=data['ymrs_total'],
            assessment_notes=data.get('assessment_notes', '')  # 备注可选
        )
        db.session.add(assessment)
        db.session.commit()
        
        return jsonify({
            'code': 200,
            'msg': '评估记录创建成功',
            'data': {'assessment_id': assessment.id}  # 用于后续提交量表详情
        })
    except ValueError:
        return jsonify({'code': 400, 'msg': '日期格式错误，需为 YYYY-MM-DD'})
    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 500, 'msg': f'创建失败：{str(e)}'})

# 3.2 医生查询患者的评估记录列表（分页）
@app.route('/api/v1/assessments/patient/<int:patient_user_id>', methods=['GET'])
@jwt_required()
def get_patient_assessments(patient_user_id):
    doctor_id = get_jwt_identity()
    # 1. 验证权限
    if not User.query.get(doctor_id) or User.query.get(doctor_id).role != 1:
        return jsonify({'code': 403, 'msg': '权限不足'})
    
    # 2. 获取分页参数（默认第1页，每页10条）
    page = request.args.get('page', 1, type=int)
    size = request.args.get('size', 10, type=int)
    
    # 3. 分页查询评估记录（按评估日期倒序）
    assessments = ScaleAssessment.query.filter_by(
        user_id=patient_user_id,
        assessor_id=doctor_id  # 只查询当前医生创建的记录
    ).order_by(ScaleAssessment.assessment_date.desc()).paginate(page=page, per_page=size)
    
    # 4. 构造返回数据
    assessment_list = []
    for ass in assessments.items:
        assessment_list.append({
            'assessment_id': ass.id,
            'assessment_date': ass.assessment_date.strftime('%Y-%m-%d'),
            'hamd_total': ass.hamd_total,
            'hama_total': ass.hama_total,
            'ymrs_total': ass.ymrs_total,
            'assessment_notes': ass.assessment_notes,
            'create_time': ass.create_time.strftime('%Y-%m-%d %H:%M:%S')
        })
    
    return jsonify({
        'code': 200,
        'data': {
            'total': assessments.total,  # 总记录数
            'pages': assessments.pages,  # 总页数
            'current_page': page,
            'list': assessment_list
        }
    })

# 新增：医生搜索患者接口（按手机号/姓名）
@app.route('/api/v1/doctor/search-patients', methods=['GET'])
@jwt_required()
def doctor_search_patients():
    doctor_id = get_jwt_identity()
    # 1. 验证当前用户是医生
    doctor = User.query.get(doctor_id)
    if not doctor or doctor.role != 1:
        return jsonify({'code': 403, 'msg': '权限不足，非医生用户'})
    
    # 2. 获取前端传递的搜索参数（手机号/姓名，支持模糊搜索姓名）
    search_phone = request.args.get('phone', '')  # 手机号（精确匹配）
    search_name = request.args.get('name', '')    # 姓名（模糊匹配，支持真实姓名/微信昵称）
    
    # 3. 校验搜索参数（至少传递一个搜索条件）
    if not search_phone and not search_name:
        return jsonify({'code': 400, 'msg': '请输入手机号或姓名进行搜索'})
    
    # 4. 构建查询条件：仅搜索角色为患者（role=2）且状态正常（status=1）的用户
    query = User.query.filter(
        User.role == 2,  # 角色为患者
        User.status == 1  # 账号正常
    )
    
    # 5. 按手机号/姓名筛选
    if search_phone:
        query = query.filter(User.phone == search_phone)  # 手机号精确匹配
    if search_name:
        # 姓名模糊匹配（同时匹配真实姓名和微信昵称）
        query = query.filter(
            db.or_(
                User.real_name.like(f'%{search_name}%'),
                User.wechat_name.like(f'%{search_name}%')
            )
        )
    
    # 6. 执行查询并构造返回数据（关联患者详情表）
    patients = query.all()
    result = []
    for patient in patients:
        # 获取患者的详细信息（年龄、性别等）
        patient_detail = UserPatient.query.filter_by(user_id=patient.id).first()
        if not patient_detail:
            continue  # 跳过未完善详情的患者
        
        # 检查该患者是否已被当前医生绑定
        is_bound = DoctorPatientBind.query.filter(
            DoctorPatientBind.doctor_id == doctor_id,
            DoctorPatientBind.patient_id == patient.id,
            DoctorPatientBind.status == 1
        ).first() is not None
        
        result.append({
            'patient_id': patient.id,  # 患者的user_id（用于后续绑定）
            'real_name': patient.real_name or patient.wechat_name,  # 优先显示真实姓名
            'phone': patient.phone or '未绑定手机号',  # 手机号
            'gender': '男' if patient_detail.gender == 1 else '女',  # 性别
            'age': patient_detail.age,  # 年龄
            'avatar': patient.wechat_avatar,  # 微信头像
            'is_bound': is_bound  # 是否已绑定（前端用于显示“绑定”/“已绑定”按钮）
        })
    
    return jsonify({
        'code': 200,
        'data': {
            'total': len(result),
            'patients': result
        }
    })

# 新增：医生绑定患者接口
@app.route('/api/v1/doctor/bind-patient', methods=['POST'])
@jwt_required()
def doctor_bind_patient():
    doctor_id = get_jwt_identity()
    data = request.get_json()
    
    # 1. 验证当前用户是医生
    doctor = User.query.get(doctor_id)
    if not doctor or doctor.role != 1:
        return jsonify({'code': 403, 'msg': '权限不足，非医生用户'})
    
    # 2. 获取前端传递的患者ID
    patient_id = data.get('patient_id')
    if not patient_id or not isinstance(patient_id, int):
        return jsonify({'code': 400, 'msg': '请选择有效的患者'})
    
    # 3. 验证患者存在且角色为患者
    patient = User.query.get(patient_id)
    patient_detail = UserPatient.query.filter_by(user_id=patient_id).first()
    if not patient or patient.role != 2:
        return jsonify({'code': 404, 'msg': '患者不存在或非患者角色'})
    if not patient_detail:
        return jsonify({'code': 400, 'msg': '该患者未完善个人详情，无法绑定'})
    
    # 4. 检查是否已绑定（避免重复绑定）
    existing_bind = DoctorPatientBind.query.filter(
        DoctorPatientBind.doctor_id == doctor_id,
        DoctorPatientBind.patient_id == patient_id,
        DoctorPatientBind.status == 1
    ).first()
    if existing_bind:
        return jsonify({'code': 400, 'msg': '已绑定该患者，无需重复操作'})
    
    # 5. 创建绑定关系（若之前解除过绑定，恢复状态而非新增）
    try:
        # 检查是否有已解除的绑定记录，有则恢复，无则新增
        inactive_bind = DoctorPatientBind.query.filter(
            DoctorPatientBind.doctor_id == doctor_id,
            DoctorPatientBind.patient_id == patient_id,
            DoctorPatientBind.status == 0
        ).first()
        
        if inactive_bind:
            inactive_bind.status = 1  # 恢复绑定状态
            inactive_bind.bind_time = datetime.datetime.now()  # 更新绑定时间
        else:
            new_bind = DoctorPatientBind(
                doctor_id=doctor_id,
                patient_id=patient_id
            )
            db.session.add(new_bind)
        
        db.session.commit()
        return jsonify({
            'code': 200,
            'msg': '患者绑定成功',
            'data': {
                'patient_id': patient_id,
                'patient_name': patient.real_name or patient.wechat_name
            }
        })
    except IntegrityError:
        db.session.rollback()
        return jsonify({'code': 400, 'msg': '绑定失败，请勿重复操作'})
    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 500, 'msg': f'绑定失败：{str(e)}'})

# 优化后的已绑定患者列表接口（合并填表情况）
@app.route('/api/v1/doctor/bound-patients', methods=['GET'])
@jwt_required()
def doctor_get_bound_patients():
    doctor_id = get_jwt_identity()
    doctor = User.query.get(doctor_id)
    if not doctor or doctor.role != 1:
        return jsonify({'code': 403, 'msg': '权限不足，非医生用户'})
    
    bind_records = DoctorPatientBind.query.filter(
        DoctorPatientBind.doctor_id == doctor_id,
        DoctorPatientBind.status == 1
    ).order_by(DoctorPatientBind.bind_time.desc()).all()
    
    bound_patients = []
    for bind in bind_records:
        patient = User.query.get(bind.patient_id)
        patient_detail = UserPatient.query.filter_by(user_id=bind.patient_id).first()
        if not patient or not patient_detail:
            continue
        
        # -------------------------- 新增：填表情况统计 --------------------------
        patient_assessments = ScaleAssessment.query.filter_by(
            user_id=bind.patient_id,
            assessor_id=doctor_id  # 仅统计当前医生的评估记录
        ).all()
        completed_scales_detail = []
        hama_completed = False
        hamd17_completed = False
        ymrs_completed = False
        for assessment in patient_assessments:
            if ScaleHama.query.filter_by(assessment_id=assessment.id).first() and '焦虑量表' not in completed_scales_detail:
                hama_completed = True
                completed_scales_detail.append('焦虑量表')
            if ScaleHamd17.query.filter_by(assessment_id=assessment.id).first() and '抑郁量表' not in completed_scales_detail:
                hamd17_completed = True
                completed_scales_detail.append('抑郁量表')
            if ScaleYmrs.query.filter_by(assessment_id=assessment.id).first() and '狂躁量表' not in completed_scales_detail:
                ymrs_completed = True
                completed_scales_detail.append('狂躁量表')
        total_scales = 3
        completed_scales = sum([hama_completed, hamd17_completed, ymrs_completed])
        # -------------------------------------------------------------------
        
        # 获取最新评估日期（原逻辑保留）
        latest_assessment = ScaleAssessment.query.filter(
            ScaleAssessment.user_id == bind.patient_id,
            ScaleAssessment.assessor_id == doctor_id
        ).order_by(ScaleAssessment.assessment_date.desc()).first()
        
        bound_patients.append({
            'patient_id': patient.id,
            'real_name': patient.real_name or patient.wechat_name,
            'phone': patient.phone or '未绑定手机号',
            'gender': '男' if patient_detail.gender == 1 else '女',
            'age': patient_detail.age,
            'avatar': patient.wechat_avatar,
            'bind_time': bind.bind_time.strftime('%Y-%m-%d %H:%M:%S'),
            'latest_assessment_date': latest_assessment.assessment_date.strftime('%Y-%m-%d') if latest_assessment else '暂无评估',
            # -------------------------- 新增：填表情况 --------------------------
            'completed_status': f"{completed_scales}/{total_scales}已完成",
            'completed_scales': completed_scales_detail
        })
    
    return jsonify({
        'code': 200,
        'data': {
            'total': len(bound_patients),
            'patients': bound_patients
        }
    })


# ------------------------------
# 4. 量表评估模块 - 细分量表接口（HAMA/HAMD17/YMRS）
# ------------------------------
# 4.1 提交HAMA焦虑量表详情
@app.route('/api/v1/assessments/<int:assessment_id>/hama', methods=['POST'])
@jwt_required()
def submit_hama(assessment_id):
    doctor_id = get_jwt_identity()
    data = request.get_json()
    
    # 1. 验证评估记录归属（确保是当前医生创建的评估）
    assessment = ScaleAssessment.query.get(assessment_id)
    if not assessment or assessment.assessor_id != doctor_id:
        return jsonify({'code': 403, 'msg': '无权限操作此评估记录'})
    
    # 2. 验证HAMA所有题目参数（共14题）
    hama_items = [
        'item1_irritability', 'item2_tension', 'item3_fears', 'item4_insomnia',
        'item5_cognition', 'item6_depressed_mood', 'item7_somatic_muscle',
        'item8_somatic_sensory', 'item9_cardiovascular', 'item10_respiratory',
        'item11_gastrointestinal', 'item12_genitourinary', 'item13_autonomic',
        'item14_behavior'
    ]
    for item in hama_items:
        if item not in data or not isinstance(data[item], int) or data[item] < 0:
            return jsonify({'code': 400, 'msg': f'HAMA题目 {item} 格式错误（需非负整数）'})
    
    # 3. 提交量表数据（若已存在则更新）
    hama_record = ScaleHama.query.filter_by(assessment_id=assessment_id).first()
    try:
        if hama_record:
            # 更新已有记录
            for item in hama_items:
                setattr(hama_record, item, data[item])
        else:
            # 创建新记录
            hama_record = ScaleHama(
                assessment_id=assessment_id,
                **{item: data[item] for item in hama_items}  # 批量传参
            )
            db.session.add(hama_record)
        db.session.commit()
        return jsonify({'code': 200, 'msg': 'HAMA量表提交成功'})
    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 500, 'msg': f'提交失败：{str(e)}'})

# 4.2 提交HAMD17抑郁量表详情（逻辑与HAMA一致，仅题目不同）
@app.route('/api/v1/assessments/<int:assessment_id>/hamd17', methods=['POST'])
@jwt_required()
def submit_hamd17(assessment_id):
    doctor_id = get_jwt_identity()
    data = request.get_json()
    
    # 1. 验证评估归属
    assessment = ScaleAssessment.query.get(assessment_id)
    if not assessment or assessment.assessor_id != doctor_id:
        return jsonify({'code': 403, 'msg': '无权限操作此评估记录'})
    
    # 2. 验证HAMD17所有题目（共17题）
    hamd17_items = [
        'item1_depression', 'item2_guilt', 'item3_suicide', 'item4_sleep_initial',
        'item5_sleep_middle', 'item6_sleep_late', 'item7_activity', 'item8_retardation',
        'item9_agitation', 'item10_anxiety_psychic', 'item11_anxiety_somatic',
        'item12_somatic_symptoms', 'item13_general_somatic', 'item14_genital',
        'item15_hypochondriasis', 'item16_weight', 'item17_insight'
    ]
    for item in hamd17_items:
        if item not in data or not isinstance(data[item], int) or data[item] < 0:
            return jsonify({'code': 400, 'msg': f'HAMD17题目 {item} 格式错误'})
    
    # 3. 提交/更新数据
    hamd17_record = ScaleHamd17.query.filter_by(assessment_id=assessment_id).first()
    try:
        if hamd17_record:
            for item in hamd17_items:
                setattr(hamd17_record, item, data[item])
        else:
            hamd17_record = ScaleHamd17(
                assessment_id=assessment_id,
                **{item: data[item] for item in hamd17_items}
            )
            db.session.add(hamd17_record)
        db.session.commit()
        return jsonify({'code': 200, 'msg': 'HAMD17量表提交成功'})
    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 500, 'msg': f'提交失败：{str(e)}'})

# 4.3 提交YMRS躁狂量表详情
@app.route('/api/v1/assessments/<int:assessment_id>/ymrs', methods=['POST'])
@jwt_required()
def submit_ymrs(assessment_id):
    doctor_id = get_jwt_identity()
    data = request.get_json()
    
    # 1. 验证评估归属
    assessment = ScaleAssessment.query.get(assessment_id)
    if not assessment or assessment.assessor_id != doctor_id:
        return jsonify({'code': 403, 'msg': '无权限操作此评估记录'})
    
    # 2. 验证YMRS所有题目（共11题）
    ymrs_items = [
        'item1_mood_elevated', 'item2_activity', 'item3_sleep', 'item4_irritability',
        'item5_speech_rate', 'item6_speech_pressured', 'item7_thought_content',
        'item8_grandiosity', 'item9_distractibility', 'item10_hostility',
        'item11_grandiosity_severity'
    ]
    for item in ymrs_items:
        if item not in data or not isinstance(data[item], int) or data[item] < 0:
            return jsonify({'code': 400, 'msg': f'YMRS题目 {item} 格式错误'})
    
    # 3. 提交/更新数据
    ymrs_record = ScaleYmrs.query.filter_by(assessment_id=assessment_id).first()
    try:
        if ymrs_record:
            for item in ymrs_items:
                setattr(ymrs_record, item, data[item])
        else:
            ymrs_record = ScaleYmrs(
                assessment_id=assessment_id,
                **{item: data[item] for item in ymrs_items}
            )
            db.session.add(ymrs_record)
        db.session.commit()
        return jsonify({'code': 200, 'msg': 'YMRS量表提交成功'})
    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 500, 'msg': f'提交失败：{str(e)}'})

# 4.4 查询指定评估的所有量表详情

@app.route('/api/v1/assessments/<int:assessment_id>/details', methods=['GET'])
@jwt_required()
def get_assessment_details(assessment_id):
    doctor_id = get_jwt_identity()
    # 1. 验证权限
    assessment = ScaleAssessment.query.get(assessment_id)
    if not assessment:
        return jsonify({'code': 404, 'msg': '评估记录不存在'})
    if assessment.assessor_id != doctor_id:
        return jsonify({'code': 403, 'msg': '无权限查看此评估详情'})

    # 2. 查询各量表数据
    hama = ScaleHama.query.filter_by(assessment_id=assessment_id).first()
    hamd17 = ScaleHamd17.query.filter_by(assessment_id=assessment_id).first()
    ymrs = ScaleYmrs.query.filter_by(assessment_id=assessment_id).first()

    # 3. 模型序列化函数（核心修复）
    def serialize_model(model):
        if not model:
            return {}
        data = {}
        # 只提取数据库表中定义的字段
        for column in model.__table__.columns:
            value = getattr(model, column.name)
            # 处理日期时间类型
            if isinstance(value, (datetime.date, datetime.datetime)):
                data[column.name] = value.strftime('%Y-%m-%d %H:%M:%S')
            else:
                data[column.name] = value
        return data

    # 4. 构造返回数据
    return jsonify({
        'code': 200,
        'data': {
            'assessment_info': {
                'assessment_id': assessment.id,
                'patient_user_id': assessment.user_id,
                'assessment_date': assessment.assessment_date.strftime('%Y-%m-%d'),
                'assessment_notes': assessment.assessment_notes
            },
            'hama': serialize_model(hama),
            'hamd17': serialize_model(hamd17),
            'ymrs': serialize_model(ymrs)
        }
    })

# ------------------------------
# 5. 统计分析模块
# ------------------------------
# 5.1 医生查询自己的评估总量（按日期范围）
@app.route('/api/v1/statistics/doctor/assessment-count', methods=['GET'])
@jwt_required()
def doctor_assessment_count():
    doctor_id = get_jwt_identity()
    # 1. 验证医生身份
    if not User.query.get(doctor_id) or User.query.get(doctor_id).role != 1:
        return jsonify({'code': 403, 'msg': '权限不足'})
    
    # 2. 获取日期范围参数（默认当月）
    start_date = request.args.get('start_date')
    end_date = request.args.get('end_date')
    if not start_date:
        start_date = datetime.now().replace(day=1).strftime('%Y-%m-%d')  # 当月1号
    if not end_date:
        end_date = datetime.now().strftime('%Y-%m-%d')  # 当天
    
    # 3. 转换日期格式并查询
    try:
        start = datetime.datetime.strptime(start_date, '%Y-%m-%d').date()
        end = datetime.datetime.strptime(end_date, '%Y-%m-%d').date()
        
        count = ScaleAssessment.query.filter(
            ScaleAssessment.assessor_id == doctor_id,
            ScaleAssessment.assessment_date >= start,
            ScaleAssessment.assessment_date <= end
        ).count()
        
        return jsonify({
            'code': 200,
            'data': {
                'start_date': start_date,
                'end_date': end_date,
                'assessment_count': count
            }
        })
    except ValueError:
        return jsonify({'code': 400, 'msg': '日期格式错误，需为 YYYY-MM-DD'})

# 5.2 管理员查询指定医院的评估总量
@app.route('/api/v1/admin/statistics/hospital/<string:hospital>/count', methods=['GET'])
@jwt_required()
def admin_hospital_count(hospital):
    admin_id = get_jwt_identity()
    # 1. 验证管理员身份
    if not User.query.get(admin_id) or User.query.get(admin_id).role != 3:
        return jsonify({'code': 403, 'msg': '权限不足'})
    
    # 2. 获取日期范围
    start_date = request.args.get('start_date', datetime.now().replace(day=1).strftime('%Y-%m-%d'))
    end_date = request.args.get('end_date', datetime.now().strftime('%Y-%m-%d'))
    
    # 3. 关联查询（医院→医生→评估记录）
    try:
        start = datetime.datetime.strptime(start_date, '%Y-%m-%d').date()
        end = datetime.datetime.strptime(end_date, '%Y-%m-%d').date()
        
        # 子查询：获取指定医院的所有医生ID
        doctor_ids = db.session.query(UserDoctor.user_id).filter(UserDoctor.hospital == hospital).subquery()
        
        # 统计这些医生的评估总量
        count = ScaleAssessment.query.filter(
            ScaleAssessment.assessor_id.in_(doctor_ids),
            ScaleAssessment.assessment_date.between(start, end)
        ).count()
        
        return jsonify({
            'code': 200,
            'data': {
                'hospital': hospital,
                'start_date': start_date,
                'end_date': end_date,
                'total_assessments': count
            }
        })
    except ValueError:
        return jsonify({'code': 400, 'msg': '日期格式错误'})
    except Exception as e:
        return jsonify({'code': 500, 'msg': f'统计失败：{str(e)}'})

# ------------------------------
# 6. 医生患者绑定管理模块
# ------------------------------
# 6.1 医生解除患者绑定接口
@app.route('/api/v1/doctor/unbind-patient', methods=['POST'])
@jwt_required()
def doctor_unbind_patient():
    doctor_id = get_jwt_identity()
    data = request.get_json()
    patient_id = data.get('patient_id')
    
    # 1. 权限与参数校验
    if not patient_id or not isinstance(patient_id, int):
        return jsonify({'code': 400, 'msg': '请选择有效的患者'})
    if not User.query.get(doctor_id) or User.query.get(doctor_id).role != 1:
        return jsonify({'code': 403, 'msg': '权限不足'})
    
    # 2. 查询绑定记录并解除
    bind_record = DoctorPatientBind.query.filter(
        DoctorPatientBind.doctor_id == doctor_id,
        DoctorPatientBind.patient_id == patient_id,
        DoctorPatientBind.status == 1
    ).first()
    if not bind_record:
        return jsonify({'code': 400, 'msg': '未绑定该患者，无需解除'})
    
    try:
        bind_record.status = 0  # 标记为已解除
        db.session.commit()
        return jsonify({'code': 200, 'msg': '患者绑定已解除'})
    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 500, 'msg': f'解除失败：{str(e)}'})


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=False)  # 生产环境关闭debug
